package cn.st4rlight.util.delay;

import java.util.Objects;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

import com.google.common.util.concurrent.MoreExecutors;

import cn.st4rlight.util.execute.ConcurrentUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * @author st4rlight <st4rlight@163.com>
 * Created on 2025-05-03
 */
@Slf4j
public class DelayTaskHelper {

    private final ExecutorService delayTaskExecutor;
    private final DelayQueue<DelayRunnableTask> delayTaskQueue = new DelayQueue<>();
    private volatile boolean stopping = false;


    public DelayTaskHelper(int delayThreadCnt) {
        this.delayTaskExecutor = ConcurrentUtil.buildThreadPool(delayThreadCnt, "delay-task-executor");
        Runtime.getRuntime().addShutdownHook(new Thread(this::shutdownDelayThreads));
        // 启动守护线程轮训延迟操作
        Thread dispatcherThread = new Thread(this::dispatchDelayTask, "delay-task-dispatcher");
        dispatcherThread.setDaemon(true);
        dispatcherThread.start();
    }

    /**
     * 提交新的延迟任务
     */
    public void addNewDelayTask(long delayMillis, Runnable runnable) {
        log.info("addNewDelayTask 添加延迟任务");
        this.delayTaskQueue.put(new DelayRunnableTask(delayMillis, runnable));
    }

    private void dispatchDelayTask() {
        log.info("dispatchDelayTask 轮训守护线程启动");
        while (!this.stopping) {
            try {
                DelayRunnableTask task = this.delayTaskQueue.poll(1, TimeUnit.SECONDS);
                if (Objects.nonNull(task)) {
                    this.delayTaskExecutor.execute(task);
                }
            } catch (Exception ex) {
                log.error("run 执行延迟任务异常", ex);
            }
        }
    }

    private void shutdownDelayThreads() {
        this.stopping = true;
        MoreExecutors.shutdownAndAwaitTermination(delayTaskExecutor, 1, TimeUnit.DAYS);
    }
}
